<?php

/**
 * JPGraph v4.0.3
 */

namespace lemon\JpGraph\Text;

use lemon\JpGraph\Plot;
use lemon\JpGraph\Util;

/*
 * File:		JPGRAPH_TABLE.PHP
 * // Description: Classes to create basic tables of data
 * // Created:	 2006-01-25
 * // Ver:		 $Id: jpgraph_table.php 1514 2009-07-07 11:15:58Z ljp $
 * //
 * // Copyright (c) Asial Corporation. All rights reserved.
 */
// Style of grid lines in table
define('TGRID_SINGLE', 1);
define('TGRID_DOUBLE', 2);
define('TGRID_DOUBLE2', 3);

// Type of constrain for image constrain
define('TIMG_WIDTH', 1);
define('TIMG_HEIGHT', 2);

/**
 * @class GTextTableCell
 * // Description:
 * // Internal class that represents each cell in the table
 */
class GTextTableCell
{
	public $iColSpan	  = 1;
	public $iRowSpan	  = 1;
	public $iMarginLeft   = 5;
	public $iMarginRight  = 5;
	public $iMarginTop	= 5;
	public $iMarginBottom = 5;
	public $iVal;
	private $iBGColor   = '';
	private $iFontColor = 'black';
	private $iFF		= FF_FONT1;
	private $iFS		= FS_NORMAL;
	private $iFSize	 = 10;
	private $iRow	   = 0;
	private $iCol	   = 0;
	private $iVertAlign = 'bottom';
	private $iHorAlign  = 'left';
	private $iMerged	= false;
	private $iPRow;
	private $iPCol;
	private $iTable;
	private $iGridColor  = ['darkgray', 'darkgray', 'darkgray', 'darkgray'];
	private $iGridWeight = [1, 1, 0, 0]; // left,top,bottom,right;
	private $iGridStyle  = [TGRID_SINGLE, TGRID_SINGLE, TGRID_SINGLE, TGRID_SINGLE]; // left,top,bottom,right;
	private $iNumberFormat;
	private $iIcon;
	private $iIconConstrain = [];
	private $iCSIMtarget	= '';
	private $iCSIMwintarget = '';
	private $iCSIMalt	   = '';
	private $iCSIMArea	  = '';

	public function __construct($aVal = '', $aRow = 0, $aCol = 0){
		$this->iVal		   = new Text($aVal);
		$this->iRow		   = $aRow;
		$this->iCol		   = $aCol;
		$this->iPRow		  = $aRow; // Initialiy each cell is its own parent
		$this->iPCol		  = $aCol;
		$this->iIconConstrain = [-1, -1];
	}

	public function Init($aTable){
		$this->iTable = $aTable;
	}

	public function SetCSIMTarget($aTarget, $aAlt = '', $aWinTarget = ''){
		$this->iCSIMtarget	= $aTarget;
		$this->iCSIMwintarget = $aWinTarget;
		$this->iCSIMalt	   = $aAlt;
	}

	public function GetCSIMArea(){
		if ($this->iCSIMtarget !== '') {
			return $this->iCSIMArea;
		}

		return '';
	}

	public function SetImageConstrain($aType, $aVal){
		if (!in_array($aType, [TIMG_WIDTH, TIMG_HEIGHT], true)) {
			Util\JpGraphError::RaiseL(27015);
		}
		$this->iIconConstrain = [$aType, $aVal];
	}

	public function SetCountryFlag($aFlag, $aScale = 1.0, $aMix = 100, $aStdSize = 3){
		$this->iIcon = new Plot\IconPlot();
		$this->iIcon->SetCountryFlag($aFlag, 0, 0, $aScale, $aMix, $aStdSize);
	}

	public function SetImage($aFile, $aScale = 1.0, $aMix = 100){
		$this->iIcon = new Plot\IconPlot($aFile, 0, 0, $aScale, $aMix);
	}

	public function SetImageFromString($aStr, $aScale = 1.0, $aMix = 100){
		$this->iIcon = new Plot\IconPlot('', 0, 0, $aScale, $aMix);
		$this->iIcon->CreateFromString($aStr);
	}

	public function SetRowColSpan($aRowSpan, $aColSpan){
		$this->iRowSpan = $aRowSpan;
		$this->iColSpan = $aColSpan;
		$this->iMerged  = true;
	}

	public function SetMerged($aPRow, $aPCol, $aFlg = true){
		$this->iMerged = $aFlg;
		$this->iPRow   = $aPRow;
		$this->iPCol   = $aPCol;
	}

	public function IsMerged(){
		return $this->iMerged;
	}

	public function SetNumberFormat($aF){
		$this->iNumberFormat = $aF;
	}

	public function Set($aTxt){
		$this->iVal->Set($aTxt);
	}

	public function SetFont($aFF, $aFS, $aFSize){
		$this->iFF	= $aFF;
		$this->iFS	= $aFS;
		$this->iFSize = $aFSize;
		$this->iVal->SetFont($aFF, $aFS, $aFSize);
	}

	public function SetFillColor($aColor){
		$this->iBGColor = $aColor;
	}

	public function SetFontColor($aColor){
		$this->iFontColor = $aColor;
	}

	public function SetGridColor($aLeft, $aTop = null, $aBottom = null, $aRight = null){
		if ($aLeft !== null) {
			$this->iGridColor[0] = $aLeft;
		}

		if ($aTop !== null) {
			$this->iGridColor[1] = $aTop;
		}

		if ($aBottom !== null) {
			$this->iGridColor[2] = $aBottom;
		}

		if ($aRight !== null) {
			$this->iGridColor[3] = $aRight;
		}
	}

	public function SetGridStyle($aLeft, $aTop = null, $aBottom = null, $aRight = null){
		if ($aLeft !== null) {
			$this->iGridStyle[0] = $aLeft;
		}

		if ($aTop !== null) {
			$this->iGridStyle[1] = $aTop;
		}

		if ($aBottom !== null) {
			$this->iGridStyle[2] = $aBottom;
		}

		if ($aRight !== null) {
			$this->iGridStyle[3] = $aRight;
		}
	}

	public function SetGridWeight($aLeft = null, $aTop = null, $aBottom = null, $aRight = null){
		if ($aLeft !== null) {
			$this->iGridWeight[0] = $aLeft;
		}

		if ($aTop !== null) {
			$this->iGridWeight[1] = $aTop;
		}

		if ($aBottom !== null) {
			$this->iGridWeight[2] = $aBottom;
		}

		if ($aRight !== null) {
			$this->iGridWeight[3] = $aRight;
		}
	}

	public function SetMargin($aLeft, $aRight, $aTop, $aBottom){
		$this->iMarginLeft   = $aLeft;
		$this->iMarginRight  = $aRight;
		$this->iMarginTop	= $aTop;
		$this->iMarginBottom = $aBottom;
	}

	public function GetWidth($aImg){
		if ($this->iIcon !== null) {
			if ($this->iIconConstrain[0] == TIMG_WIDTH) {
				$this->iIcon->SetScale(1);
				$tmp = $this->iIcon->GetWidthHeight();
				$this->iIcon->SetScale($this->iIconConstrain[1] / $tmp[0]);
			} elseif ($this->iIconConstrain[0] == TIMG_HEIGHT) {
				$this->iIcon->SetScale(1);
				$tmp = $this->iIcon->GetWidthHeight();
				$this->iIcon->SetScale($this->iIconConstrain[1] / $tmp[1]);
			}
			$tmp	= $this->iIcon->GetWidthHeight();
			$iwidth = $tmp[0];
		} else {
			$iwidth = 0;
		}
		if ($this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->dir == 0) {
			$pwidth = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetWidth($aImg);
		} elseif ($this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->dir == 90) {
			$pwidth = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetFontHeight($aImg) + 2;
		} else {
			$pwidth = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetWidth($aImg) + 2;
		}

		$pcolspan = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iColSpan;

		return round(max($iwidth, $pwidth) / $pcolspan) + $this->iMarginLeft + $this->iMarginRight;
	}

	public function GetHeight($aImg){
		if ($this->iIcon !== null) {
			if ($this->iIconConstrain[0] == TIMG_WIDTH) {
				$this->iIcon->SetScale(1);
				$tmp = $this->iIcon->GetWidthHeight();
				$this->iIcon->SetScale($this->iIconConstrain[1] / $tmp[0]);
			} elseif ($this->iIconConstrain[0] == TIMG_HEIGHT) {
				$this->iIcon->SetScale(1);
				$tmp = $this->iIcon->GetWidthHeight();
				$this->iIcon->SetScale($this->iIconConstrain[1] / $tmp[1]);
			}
			$tmp	 = $this->iIcon->GetWidthHeight();
			$iheight = $tmp[1];
		} else {
			$iheight = 0;
		}
		if ($this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->dir == 0) {
			$pheight = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetHeight($aImg);
		} else {
			$pheight = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iVal->GetHeight($aImg) + 1;
		}
		$prowspan = $this->iTable->iCells[$this->iPRow][$this->iPCol]->iRowSpan;

		return round(max($iheight, $pheight) / $prowspan) + $this->iMarginTop + $this->iMarginBottom;
	}

	public function SetAlign($aHorAlign = 'left', $aVertAlign = 'bottom'){
		$aHorAlign  = strtolower($aHorAlign);
		$aVertAlign = strtolower($aVertAlign);
		$chk		= ['left', 'right', 'center', 'bottom', 'top', 'middle'];
		if (!in_array($aHorAlign, $chk, true) || !in_array($aVertAlign, $chk, true)) {
			Util\JpGraphError::RaiseL(27011, $aHorAlign, $aVertAlign);
		}
		$this->iVertAlign = $aVertAlign;
		$this->iHorAlign  = $aHorAlign;
	}

	public function AdjustMarginsForGrid(){
		if ($this->iCol > 0) {
			switch ($this->iGridStyle[0]) {
				case TGRID_SINGLE:$wf = 1;

					break;
				case TGRID_DOUBLE:$wf = 3;

					break;
				case TGRID_DOUBLE2:$wf = 4;

					break;
			}
			$this->iMarginLeft += $this->iGridWeight[0] * $wf;
		}
		if ($this->iRow > 0) {
			switch ($this->iGridStyle[1]) {
				case TGRID_SINGLE:$wf = 1;

					break;
				case TGRID_DOUBLE:$wf = 3;

					break;
				case TGRID_DOUBLE2:$wf = 4;

					break;
			}
			$this->iMarginTop += $this->iGridWeight[1] * $wf;
		}
		if ($this->iRow + $this->iRowSpan - 1 < $this->iTable->iSize[0] - 1) {
			switch ($this->iGridStyle[2]) {
				case TGRID_SINGLE:$wf = 1;

					break;
				case TGRID_DOUBLE:$wf = 3;

					break;
				case TGRID_DOUBLE2:$wf = 4;

					break;
			}
			$this->iMarginBottom += $this->iGridWeight[2] * $wf;
		}
		if ($this->iCol + $this->iColSpan - 1 < $this->iTable->iSize[1] - 1) {
			switch ($this->iGridStyle[3]) {
				case TGRID_SINGLE:$wf = 1;

					break;
				case TGRID_DOUBLE:$wf = 3;

					break;
				case TGRID_DOUBLE2:$wf = 4;

					break;
			}
			$this->iMarginRight += $this->iGridWeight[3] * $wf;
		}
	}

	public function StrokeVGrid($aImg, $aX, $aY, $aWidth, $aHeight, $aDir = 1){
		// Left or right grid line
		// For the right we increase the X-pos and for the right we decrease it. This is
		// determined by the direction argument.
		$idx = $aDir == 1 ? 0 : 3;

		// We don't stroke the grid lines that are on the edge of the table since this is
		// the place of the border.
		if ((($this->iCol > 0 && $idx == 0) || ($this->iCol + $this->iColSpan - 1 < $this->iTable->iSize[1] - 1 && $idx == 3))
			&& $this->iGridWeight[$idx] > 0) {
			$x = $aDir == 1 ? $aX : $aX + $aWidth - 1;
			$y = $aY + $aHeight - 1;
			$aImg->SetColor($this->iGridColor[$idx]);
			switch ($this->iGridStyle[$idx]) {
				case TGRID_SINGLE:
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($x + $i * $aDir, $aY, $x + $i * $aDir, $y);
					}

					break;
				case TGRID_DOUBLE:
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($x + $i * $aDir, $aY, $x + $i * $aDir, $y);
					}

					$x += $this->iGridWeight[$idx] * 2;
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($x + $i * $aDir, $aY, $x + $i * $aDir, $y);
					}

					break;
				case TGRID_DOUBLE2:
					for ($i = 0; $i < $this->iGridWeight[$idx] * 2; ++$i) {
						$aImg->Line($x + $i * $aDir, $aY, $x + $i * $aDir, $y);
					}

					$x += $this->iGridWeight[$idx] * 3;
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($x + $i * $aDir, $aY, $x + $i * $aDir, $y);
					}

					break;
			}
		}
	}

	public function StrokeHGrid($aImg, $aX, $aY, $aWidth, $aHeight, $aDir = 1){
		// Top or bottom grid line
		// For the left we increase the X-pos and for the right we decrease it. This is
		// determined by the direction argument.
		$idx = $aDir == 1 ? 1 : 2;

		// We don't stroke the grid lines that are on the edge of the table since this is
		// the place of the border.
		if ((($this->iRow > 0 && $idx == 1) || ($this->iRow + $this->iRowSpan - 1 < $this->iTable->iSize[0] - 1 && $idx == 2))
			&& $this->iGridWeight[$idx] > 0) {
			$y = $aDir == 1 ? $aY : $aY + $aHeight - 1;
			$x = $aX + $aWidth - 1;
			$aImg->SetColor($this->iGridColor[$idx]);
			switch ($this->iGridStyle[$idx]) {
				case TGRID_SINGLE:
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($aX, $y + $i, $x, $y + $i);
					}

					break;
				case TGRID_DOUBLE:
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($aX, $y + $i, $x, $y + $i);
					}

					$y += $this->iGridWeight[$idx] * 2;
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($aX, $y + $i, $x, $y + $i);
					}

					break;
				case TGRID_DOUBLE2:
					for ($i = 0; $i < $this->iGridWeight[$idx] * 2; ++$i) {
						$aImg->Line($aX, $y + $i, $x, $y + $i);
					}

					$y += $this->iGridWeight[$idx] * 3;
					for ($i = 0; $i < $this->iGridWeight[$idx]; ++$i) {
						$aImg->Line($aX, $y + $i, $x, $y + $i);
					}

					break;
			}
		}
	}

	public function Stroke($aImg, $aX, $aY, $aWidth, $aHeight){
		// If this is a merged cell we only stroke if it is the parent cell.
		// The parent cell holds the merged cell block
		if ($this->iMerged && ($this->iRow != $this->iPRow || $this->iCol != $this->iPCol)) {
			return;
		}

		if ($this->iBGColor != '') {
			$aImg->SetColor($this->iBGColor);
			$aImg->FilledRectangle($aX, $aY, $aX + $aWidth - 1, $aY + $aHeight - 1);
		}

		$coords = $aX . ',' . $aY . ',' . ($aX + $aWidth - 1) . ',' . $aY . ',' . ($aX + $aWidth - 1) . ',' . ($aY + $aHeight - 1) . ',' . $aX . ',' . ($aY + $aHeight - 1);
		if (!empty($this->iCSIMtarget)) {
			$this->iCSIMArea = '<area shape="poly" coords="' . $coords . '" href="' . $this->iCSIMtarget . '"';
			if (!empty($this->iCSIMwintarget)) {
				$this->iCSIMArea .= ' target="' . $this->iCSIMwintarget . '"';
			}
			if (!empty($this->iCSIMalt)) {
				$this->iCSIMArea .= ' alt="' . $this->iCSIMalt . '" title="' . $this->iCSIMalt . '" ';
			}
			$this->iCSIMArea .= " />\n";
		}

		$this->StrokeVGrid($aImg, $aX, $aY, $aWidth, $aHeight);
		$this->StrokeVGrid($aImg, $aX, $aY, $aWidth, $aHeight, -1);
		$this->StrokeHGrid($aImg, $aX, $aY, $aWidth, $aHeight);
		$this->StrokeHGrid($aImg, $aX, $aY, $aWidth, $aHeight, -1);

		if ($this->iIcon !== null) {
			switch ($this->iHorAlign) {
				case 'left':
					$x	   = $aX + $this->iMarginLeft;
					$hanchor = 'left';

					break;
				case 'center':
				case 'middle':
					$x	   = $aX + $this->iMarginLeft + round(($aWidth - $this->iMarginLeft - $this->iMarginRight) / 2);
					$hanchor = 'center';

					break;
				case 'right':
					$x	   = $aX + $aWidth - $this->iMarginRight - 1;
					$hanchor = 'right';

					break;
				default:
					Util\JpGraphError::RaiseL(27012, $this->iHorAlign);
			}

			switch ($this->iVertAlign) {
				case 'top':
					$y	   = $aY + $this->iMarginTop;
					$vanchor = 'top';

					break;
				case 'center':
				case 'middle':
					$y	   = $aY + $this->iMarginTop + round(($aHeight - $this->iMarginTop - $this->iMarginBottom) / 2);
					$vanchor = 'center';

					break;
				case 'bottom':
					$y	   = $aY + $aHeight - 1 - $this->iMarginBottom;
					$vanchor = 'bottom';

					break;
				default:
					Util\JpGraphError::RaiseL(27012, $this->iVertAlign);
			}
			$this->iIcon->SetAnchor($hanchor, $vanchor);
			$this->iIcon->_Stroke($aImg, $x, $y);
		}
		$this->iVal->SetColor($this->iFontColor);
		$this->iVal->SetFont($this->iFF, $this->iFS, $this->iFSize);
		switch ($this->iHorAlign) {
			case 'left':
				$x = $aX + $this->iMarginLeft;

				break;
			case 'center':
			case 'middle':
				$x = $aX + $this->iMarginLeft + round(($aWidth - $this->iMarginLeft - $this->iMarginRight) / 2);

				break;
			case 'right':
				$x = $aX + $aWidth - $this->iMarginRight - 1;

				break;
			default:
				Util\JpGraphError::RaiseL(27012, $this->iHorAlign);
		}
		// A workaround for the shortcomings in the TTF font handling in GD
		// The anchor position for rotated text (=90) is to "short" so we add
		// an offset based on the actual font size
		if ($this->iVal->dir != 0 && $this->iVal->font_family >= 10) {
			$aY += 4 + round($this->iVal->font_size * 0.8);
		}
		switch ($this->iVertAlign) {
			case 'top':
				$y = $aY + $this->iMarginTop;

				break;
			case 'center':
			case 'middle':
				$y = $aY + $this->iMarginTop + round(($aHeight - $this->iMarginTop - $this->iMarginBottom) / 2);
				//$y -= round($this->iVal->GetFontHeight($aImg)/2);
				$y -= round($this->iVal->GetHeight($aImg) / 2);

				break;
			case 'bottom':
				//$y = $aY+$aHeight-1-$this->iMarginBottom-$this->iVal->GetFontHeight($aImg);
				$y = $aY + $aHeight - $this->iMarginBottom - $this->iVal->GetHeight($aImg);

				break;
			default:
				Util\JpGraphError::RaiseL(27012, $this->iVertAlign);
		}
		$this->iVal->SetAlign($this->iHorAlign, 'top');
		if ($this->iNumberFormat !== null && is_numeric($this->iVal->t)) {
			$this->iVal->t = sprintf($this->iNumberFormat, $this->iVal->t);
		}
		$this->iVal->Stroke($aImg, $x, $y);
	}
}

/*
EOF
 */
